package cn.edu.neu.vmmigeval.cloud.policy.mgrdsm;

import cn.edu.neu.vmmigeval.cloud.entity.Host;
import cn.edu.neu.vmmigeval.cloud.entity.Vm;
import cn.edu.neu.vmmigeval.cloud.policy.MigratedHostPolicy;
import cn.edu.neu.vmmigeval.cloud.policy.VmSelectionPolicy;
import cn.edu.neu.vmmigeval.evaluation.loadevaluation.LoadCombination;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * The Minimum Utilization (MU) Broker selection policy.
 * @author zzh
 *
 */
public class VmSelectionPolicyMGSM extends VmSelectionPolicy {

	public VmSelectionPolicyMGSM(
			MigratedHostPolicy migratedHostPolicy) {
		super(migratedHostPolicy);
	}

	public VmSelectionPolicyMGSM(){

	}
	private String getHostType(Host host){
		double cpu = host.getCurrentCpu()/host.getTotalCpu();
		double ram  =  host.getCurrentRam()/host.getTotalRam();
		double bw = host.getCurrentBw()/host.getTotalBw();
		double disk = host.getCurrentDisk()/host.getTotalDisk();
		if(cpu>=ram && cpu>=bw && cpu>=disk){
			return "cpu";
		}else if(ram>=cpu && ram>=bw && ram>=disk){
			return "ram";
		}else if(bw>=cpu && bw>=ram && bw>=disk){
			return "bw";
		}else{
			return "disk";
		}
	}

	@Override
	public List<Vm> getMigratedVmsfromHost(Host host){
		//System.out.println("���ҽڵ�"+host.getId()+"��Cpu���޴�����ҪǨ�Ƶ�������ļ���");
		//�õ���ǰhost�ϵ����������
		List<Vm> destVms = null;
		List<Vm> vms = new ArrayList<Vm>();
		for(Vm vm:host.getVmList()){
			if(!vm.isInMigration()){
				vms.add(vm);
			}
		}if(host.getLoadFlag()==0){
			if(vms!=null&&vms.size()!=0){

				String type = getHostType(host);
				double cpuWeight = 0.2,ramWeight=0.2,bwWeight=0.2,diskWeight = 0.2;
				if(type=="cpu"){
					cpuWeight = cpuWeight*2;
				}else if(type=="ram"){
					ramWeight = ramWeight*2;
				}else if(type=="bw"){
					bwWeight = bwWeight*2;
				}else if(type=="disk"){
					diskWeight = diskWeight*2;
				}
				double hostLoad = host.getCurrentCpu()/host.getTotalCpu()*cpuWeight+host.getCurrentRam()/host.getTotalRam()*ramWeight
						+host.getCurrentBw()/host.getTotalBw()*bwWeight+host.getCurrentDisk()/host.getTotalDisk()*diskWeight;
				LoadCombination lc = new LoadCombination();
				Map<Integer, List<Vm>> map = lc.getVmMap(vms);
				Map<Integer,Double> map2 = new HashMap<Integer,Double>();
				int index =1;
				for (Entry<Integer,List<Vm>> entry : map.entrySet()) {
					
				/*}
				for (List<Vm> li : map.values()) {*/
					double sum =0;
					for (Vm vm : entry.getValue()) {
						sum+=vm.getCurrentCpu()/vm.getTotalCpu()*cpuWeight+vm.getCurrentRam()/vm.getTotalRam()*ramWeight
								+vm.getCurrentBw()/vm.getTotalBw()*bwWeight+vm.getCurrentDisk()/vm.getTotalDisk()*diskWeight;
					}
					map2.put(index++, sum);
				}
				double min = 10;
				Integer flag =1;
				for (Entry<Integer,Double> entry : map2.entrySet()) {
					if(entry.getValue()/hostLoad>=0.1){
						if(entry.getValue()<min){
							min = entry.getValue();
							flag = entry.getKey();
						}
					}
				}
				destVms = map.get(flag);
			}
		}else{
			destVms = host.getVmList();
		}

		return destVms;
	}

	@Override
	public Vm getVmToMigrate(Host host) {

		return null;
	}

}
